<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/27
 * Time: 14:05
 */

namespace app\common\services;


use app\common\model\OrderPaymentLog;
use app\common\model\Orders;
use app\common\model\User;
use app\common\model\UserDistribution;
use app\common\payment\wxpay\JsApiPay;
use app\common\payment\wxpay\lib\WxPayApi;
use app\common\payment\wxpay\lib\WxPayOrderQuery;
use app\common\payment\wxpay\lib\WxPayUnifiedOrder;
use app\common\payment\wxpay\PayNotifyCallBack;
use app\common\payment\wxpay\WxPayConfig;
use think\Db;
use think\Exception;
use think\facade\Config;

class WxpayService
{

    public function ttOrder($params,$topicInfo,$userInfo){
        /**
         * 组织头条下单基础字段数据
         */
        $orderInfo = array();
        $orderInfo['app_id'] = Config::get('params.tt_pay_app_id');
        $orderInfo['merchant_id'] = Config::get('params.tt_pay_merchant_id');
        $orderInfo['timestamp'] = time().'';
        $orderInfo['sign_type'] = 'MD5';
        $orderInfo['out_order_no'] = $this->build_order_no();
        $orderInfo['total_amount'] = round($topicInfo['tt_play_price'] * 100);//费用单位为分 取整;
        $orderInfo['product_code'] = 'pay';
        $orderInfo['trade_type'] = 'H5';
        $orderInfo['version'] = '2.0';
        $orderInfo['payment_type'] = 'direct';
        $orderInfo['currency'] = 'CNY';
        $orderInfo['subject'] = Config::get('params.tt_pay_order_subject');
        $orderInfo['body'] = Config::get('params.tt_pay_order_subject');
        $orderInfo['uid'] = str_pad($userInfo['user_id'],32,'CP',STR_PAD_LEFT);
        $orderInfo['trade_time'] = time().'';
        $orderInfo['valid_time'] = 1800;
        $orderInfo['notify_url'] = Config::get('params.php_server');
        $orderInfo['wx_type'] = 'MWEB';
        $orderInfo['wx_url'] = '';//微信支付统一下单里的web_url
        $orderInfo['alipay_url'] = '';
        $orderInfo['risk_info'] = ['ip'=>get_client_ip()]; //必须返回，获得秘钥不需要传入加密


        //走微信H5统一下单功能，并存储订单信息到数据库中
        //走下单流程
        writeLog(666666666666666666666,'支付下单信息流程--service');

        Db::startTrans();
        try{

            (new Orders())->addOrder($userInfo,$orderInfo,$topicInfo);
            Db::commit();

            //走微信H5统一下单接口
            if(Config::get('params.tt_use_wechat')){
                writeLog('进入微信下单接口','支付下单流程');
                $orderInfo['wx_url'] = $this->H5unifiedOrder($orderInfo,$topicInfo);
            }
            if(Config::get('params.tt_use_alipay'))  {
                writeLog('进入支付宝下单接口','支付下单流程');
                $orderInfo['alipay_url'] = (new AlipayService())->getAppOrder($orderInfo,$topicInfo);
            }

            $orderInfo['sign'] = getTtSignature($orderInfo,Config::get('params.tt_pay_app_secret'));

        }catch (Exception $e){
            writeLog($e->getMessage(),'支付过程下单失败原因');
            wapAjaxReturn(400,'下单失败，请反馈客服',$e->getMessage());
            Db::rollback();
        }

        return $orderInfo;
    }

    /**
     * 实例微信H5统一下单
     * @return array
     */
    public function H5unifiedOrder($orderInfo,$topicInfo){
        writeLog('进入unifiedOrder','支付下单信息流程--service');
        try{
            //②、统一下单
            $input = new WxPayUnifiedOrder();
            $input->SetBody(Config::get('params.tt_pay_order_subject')); //商品描述  是
            $input->SetOut_trade_no($orderInfo['out_order_no']); //商户订单号 是
            $input->SetFee_type('CNY');//标价币种 否
            $input->SetTotal_fee($orderInfo['total_amount']);//标价金额  是
            $input->SetSpbill_create_ip(get_client_ip());// 终端ip 是
            $input->SetTime_start(date('YmdHis',$orderInfo['trade_time'])); //交易起始时间 否
            $input->SetTime_expire(date('YmdHis',($orderInfo['trade_time']+$orderInfo['valid_time']))); //交易结束时间 否
            $input->SetTrade_type('MWEB');//交易类型 是 微信内支付用这个类型
            $input->SetNotify_url(Config::get('params.notify_url'));
            $config = new WxPayConfig();
            writeLog($input,'支付下单信息流程--service');
            writeLog($config,'支付下单信息流程--service');
            $order = WxPayApi::unifiedOrder($config, $input);
            if($order['return_code'] == 'SUCCESS' && $order['result_code'] == 'SUCCESS'){
//                $jsApiParameters = $tools->GetJsApiParameters($order);
                return $order['mweb_url'];
            }
            throw new Exception('微信H5统一下单失败2');
        }catch (\Exception $e){
            writeLog($e->getMessage(),'微信H5下单异常信息');
            throw new Exception('微信H5统一下单异常');
        }
    }


    /**
     * 微信支付回调响应
     */
    public function payNotifyCallBack(){
        try{
            writeLog('开始响应','支付回调信息');
            $config = new WxPayConfig();
            $notify = new PayNotifyCallBack();
            $notify->Handle($config, false);
        }catch (\Exception $e){
            writeLog($e->getMessage(),'支付回调-执行程序出错');
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>';
        }
    }


    /**
     * 支付回调业务处理方法
     * @param $data
     * @return bool
     * @throws \yii\db\Exception
     */
    public function payCallbackDeal($data){
        writeLog('进入payCallbackDeal方法','支付回调信息');
        Db::startTrans();
        try{
            //根据订单号查询数据
            $orderInfo = Orders::where(
                [
                    ['order_sn','=',$data['out_trade_no']]
                    ,['status','<>',2]
                ])->find();
            if(!$orderInfo){
                writeLog('没找到对应的订单信息','支付回调信息');
                return true; //没找到合适 无需操作
            }
            if(round($orderInfo->amount * 100) != $data['total_fee']){ //金额没匹配上
                writeLog('金额没匹配上','支付回调信息');
                return false;
            }
            $orderInfo->pay_type = !empty($data['pay_type'])?$data['pay_type']:1;//1-微信支付 2-支付宝支付
            $orderInfo->status = 2;
            $orderInfo->updated_time = time();
            $orderInfo->save();
            //增加记录，将对应的缴费信息给更新为已缴费
            $payLog = new OrderPaymentLog();
            $payLog->order_sn = $orderInfo->order_sn;
            $payLog->order_id = $orderInfo->order_id;
            $payLog->pay_code = $data['transaction_id'];
            $payLog->amount = $data['total_fee']/100;
            $payLog->status = 3;
            $payLog->callback_time =time();
            $payLog->create_time = time();
            $payLog->update_time = time();
            $payLog->callback_info = json_encode($data);
            $payLog->pay_time = strtotime($data['time_end']);
            $payLog->save();

            /**
             * 判断是否有分销佣金生成，根据实际支付金额以及分佣比例处理，并且判断当前支付订单的用户
             * 是否有上级用户，有才做分佣逻辑处理
             */

            $userInfo = (new User())->getUserInfo($orderInfo->user_id);
            if($userInfo != null && $orderInfo->fir_distribution > 0){
                //不四舍五入，保留两位小数点
                $get_price = substr(sprintf("%.3f",$orderInfo->amount * $orderInfo->fir_distribution / 100),0,-1);
                if($get_price >0){
                    $distribution['user_id'] = $userInfo->fir_distribution;
                    $distribution['order_id'] = $orderInfo->order_id;
                    $distribution['topic_id'] = $orderInfo->property_ids;
                    $distribution['distribution_percent'] = $orderInfo->fir_distribution;
                    $distribution['origin_price'] = $orderInfo->amount;
                    $distribution['get_price'] = $get_price;
                    $distribution['created_at'] = time();
                    $distribution['type'] = 1;
                    $distribution['true_price'] = $get_price;
                    $distribution['price_deal_staus'] = 1;
                    $distribution['priece_deal_at'] = time();
                    $distribution['origin_user_id'] = $userInfo->user_id;
                    $distribution['user_type'] = 1;

                    $orderDistribution = new UserDistribution();
                    $save = $orderDistribution->allowField(true)->save($distribution);
                    if(!$save){throw  new Exception('下单存储数据存储失败');}


                    $addUser = (new User())->getUserInfo($userInfo->fir_distribution);
                    if($addUser != null){
                        $addUser->money = $addUser->money + $get_price;
                        $addUser->total_money = $addUser->total_money + $get_price;
                        $addUser->save();
                    }
                }
            }

            /**
             * 判断当前用户是否需要操作二级分销的返利
             */
            if($userInfo != null && $orderInfo->sec_distribution > 0){
                //不四舍五入，保留两位小数点
                $get_price2 = substr(sprintf("%.3f",$orderInfo->amount * $orderInfo->sec_distribution / 100),0,-1);
                if($get_price2 >0){
                    $distribution['user_id'] = $userInfo->sec_distribution;
                    $distribution['order_id'] = $orderInfo->order_id;
                    $distribution['topic_id'] = $orderInfo->property_ids;
                    $distribution['distribution_percent'] = $orderInfo->sec_distribution;
                    $distribution['origin_price'] = $orderInfo->amount;
                    $distribution['get_price'] = $get_price2;
                    $distribution['created_at'] = time();
                    $distribution['type'] = 1;
                    $distribution['true_price'] = $get_price2;
                    $distribution['price_deal_staus'] = 1;
                    $distribution['priece_deal_at'] = time();
                    $distribution['origin_user_id'] = $userInfo->user_id;
                    $distribution['user_type'] = 2;

                    $orderDistribution = new UserDistribution();
                    $save = $orderDistribution->allowField(true)->save($distribution);
                    if(!$save){throw  new Exception('下单存储数据存储失败');}


                    $addUser2 = (new User())->getUserInfo($userInfo->sec_distribution);
                    if($addUser2 != null){
                        $addUser2->money = $addUser2->money + $get_price2;
                        $addUser2->total_money = $addUser2->total_money + $get_price2;
                        $addUser2->save();
                    }
                }
            }


            if($orderInfo->order_id && $payLog->id){
                writeLog('支付回调处理成功','支付回调信息');
                Db::commit();return true;
            }
            writeLog('支付回调处理失败','支付回调信息');
            Db::rollBack();return false;
        }catch (\Exception $e){
            writeLog('业务逻辑执行错误','支付回调信息');
            writeLog($e->getMessage(),'支付回调信息');
            Db::rollBack();
            return false;
        }
    }


    /**
     * 查询微信订单
     * @param $out_order_no
     */
    public function queryOrder($out_order_no){
        $input = new WxPayOrderQuery();
        $input->SetOut_trade_no($out_order_no);
        $config = new WxPayConfig();
        $order = (new WxPayApi())->orderQuery($config, $input);
        return $order;
    }









    /**
     *生成订单号
     * uniqid - 官方是这样说的：
     * Gets a prefixed unique identifier based on the current time in microseconds.
     */
    function build_order_no()
    {
        return 'CP'.date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }
}